package com.autologistics.socket.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import com.autologistics.socket.vo.AuthenticationRes;
import com.autologistics.socket.vo.FomatErrorRes;
import com.autologistics.socket.vo.OrderGetRes;
import com.autologistics.socket.vo.OrderWaitGetRes;
import com.autologistics.socket.vo.StateReportRes;

import net.sf.json.JSONException;
import net.sf.json.JSONObject;

public class ServerListner {

	/*
	 * 0.uninit
	 * 1.started
	 * 2.stop
	 * 3.error
	 */
	private int state=0;
	private String errorDescription;
	private ServerSocket ss = null;
	
	public synchronized String start(){
		if(state == 0){
			init();
		}
		excute();
		while(state != 0 && state !=2){
			
		}
		
		return errorDescription;
	}
	
	public synchronized void stop(){
		if(state == 2)
			return;
		try {
			ss.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		state =2;
	}
	
	public synchronized void resume(){
		
	}
	
	protected void init() {
		//we do nothing
	}
	protected void excute(){
		// listener thread
		new Thread(){

			@Override
			public void run() {
				
				try {
					ss = new ServerSocket(50002);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					//errorDescription = "绔彛鐩戝惉寮傚父锛岃纭疄绔彛鏄惁琚叾浠栬繘绋嬪崰鐢�;
					state = 3;
					System.out.println(e.getMessage());
					return;
				}

				state =1;
				while(state==1){
					try {
						Socket so = ss.accept();
						new ConnectProcess(so).start();
					} catch(SocketException e1){
						state = 2;
					}catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				try {
					ss.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		}.start();
	}
	
	protected class ConnectProcess extends Thread{

		Socket so = null;
		
		public ConnectProcess(Socket so) {
			this.so = so;
		}

		@Override
		public void run() {
			if(so == null){
				return;
			}
			JSONObject retJson = null;
			String method ="";
			try {
				
				//BufferedReader br = new BufferedReader(new InputStreamReader(so.getInputStream()));
				InputStream is = so.getInputStream();
				StringBuilder sb = new StringBuilder();
				byte[] space = new byte[1024];
				int n =0;
				while((n=is.read(space)) == 1024){
					sb.append(new String(space,0,n));
				}
				sb.append(new String(space,0,n));
				LogAppender.appendLog("from machine:"+sb.toString());
				JSONObject jsonObject = null;
				try{
					jsonObject = JSONObject.fromObject(sb.toString());
				}catch(JSONException e){
					jsonObject = null;
					LogAppender.appendLog(e.getMessage());
				}
				
				if(jsonObject == null){
					//handle request format exception 
					FomatErrorRes fomatErrorRes = new FomatErrorRes();
					fomatErrorRes.setResponseDescription("request is not a json fomat string");
					retJson = JSONObject.fromObject(fomatErrorRes);
				}else{
					method = jsonObject.optString("requestMethod","unDefine");
					jsonObject.put("machineip", so.getInetAddress().getHostAddress());
					if(method.equals("IDAuthentication")){
						retJson = new IDAuthenticationServices(jsonObject).IDAuthenticatin();
					}else if(method.equals("OrderGet")){
						retJson = new OrderServices(jsonObject).orderGet();
					}else if(method.equals("OrderWaitGet")){
						retJson = new OrderServices(jsonObject).orderWaiteGet();
					}else if(method.equals("StateReport")){
						retJson = new ReportServices(jsonObject).processMachineReport();
					}else if(method.equals("MachineReqMediaFile")){
						
					}else{
						FomatErrorRes fomatErrorRes = new FomatErrorRes();
						fomatErrorRes.setResponseDescription("request method not defined on server,this is a low verison server?");
						retJson = JSONObject.fromObject(fomatErrorRes);
					}
				}
				
				OutputStream os = so.getOutputStream();
				
				os.write(retJson.toString().getBytes());
				os.close();
				is.close();
				so.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				LogAppender.appendLog("server error: "+e.getMessage());//this exception could not response to machine
			}catch(Exception e){
				e.printStackTrace();
				LogAppender.appendLog("server error: "+e.getMessage());
				
				if(method.equals("IDAuthentication")){
					AuthenticationRes res = new AuthenticationRes();
					res.setResponseCode(2);
					res.setResponseDescription(e.getMessage());
					retJson = JSONObject.fromObject(res);
				}else if(method.equals("OrderGet")){
					OrderGetRes res = new OrderGetRes();
					res.setResponseCode(2);
					res.setResponseDescription(e.getMessage());
					retJson = JSONObject.fromObject(res);
				}else if(method.equals("OrderWaitGet")){
					OrderWaitGetRes res = new OrderWaitGetRes();
					res.setResponseCode(3);
					res.setResponseDescription(e.getMessage());
					retJson = JSONObject.fromObject(res);
				}else if(method.equals("StateReport")){
					StateReportRes res = new StateReportRes();
					res.setResponseCode(2);
					res.setResponseDescription(e.getMessage());
					retJson = JSONObject.fromObject(res);
				}else{
					FomatErrorRes fomatErrorRes = new FomatErrorRes();
					fomatErrorRes.setResponseDescription("request method not defined on server,this is a low verison server?");
					retJson = JSONObject.fromObject(fomatErrorRes);
				}

				try {
					OutputStream os = so.getOutputStream();

					os.write(retJson.toString().getBytes());
					os.close();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
					LogAppender.appendLog("server error: "+e1.getMessage());
				}
				
			}
			finally{
				try{
					so.close();
				}catch(Exception e){
					//do nothing
				}
				if(retJson == null){
					LogAppender.appendLog("to machine: server error ,response is null");
				}else{
					LogAppender.appendLog("to machine:"+retJson.toString());
				}
				
			}
		}
		
	}
}
